package com.server;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

public class Plasma {

    private static final double K1 = 70;
    private static final double K2 = 80;
    private static final double K3 = 60;

    private final int kSin1 = (int) (K1 * (360 / 57.3));
    private final int kSin2 = (int) (K2 * (360 / 57.3));
    private final int kSin3 = (int) (K3 * (360 / 57.3));

    private final int[] sinLut1 = new int[2048 * 4];
    private final int[] sinLut2 = new int[2048 * 4];
    private final int[] sinLut3;
    private int a, b, c;
    BufferedImage image = new BufferedImage(78,39,BufferedImage.TYPE_INT_RGB);
    int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

    BufferedImage texture = new BufferedImage(256,256,BufferedImage.TYPE_INT_RGB);
    int[] texPixels = ((DataBufferInt) texture.getRaster().getDataBuffer()).getData();

    public Plasma() {
        this.sinLut3 = new int[2048 * 4];
        int size = sinLut1.length;
        for (int i = 0; i < size; i++) {
            sinLut1[i] = (int) (Math.sin(i / K1) * 127 + Math.cos(i / K1) * 67);
            sinLut2[i] = (int) (Math.sin(i / K2) * 164 + Math.cos(i / K2) * 26);
            sinLut3[i] = (int) (Math.sin(i / K3) * 32 + Math.cos(i / K3) * 280);
        }

        double j = 255 / 360.0f * 3;
        double k = 255 / 360.0f * 2;
        double l = 255 / 360.0f * 1;
        double pa = 0;
        double pb = 0;
        double pc = 0;
        for (int y = 0; y < 256; y++) {
            int tR = (int) (255 * Math.abs(Math.sin(pa * Math.PI / 180.0)));
            int tG = (int) (255 * Math.abs(Math.sin(pb * Math.PI / 180.0)));
            int tB = (int) (255 * Math.abs(Math.sin(pc * Math.PI / 180.0)));
            c = (255 << 24) | (tR << 16) | (tG << 8) | (tB);
            for (int x = 0; x < 256; x++) {
                texPixels[y * 256 + x] = c;
            }
            
            pa += j;
            pb += k;
            pc += l;
        }
    }

    public void update() {
        a = (++a) % (kSin1 + 1);
        b = (++b) % (kSin2 + 1);
        c = (++c) % (kSin3 + 1);
        int offset = 0;
        for (int y = 0; y < 39; y++) {
            for (int x = 0; x < 78; x++) {
                int tx = (sinLut1[x + a + 2048]
                        + sinLut2[y + b + 2048]
                        + sinLut3[x + y + c + 2048]);
                int ty = (sinLut3[x + y + c + 2048]
                        + sinLut1[(tx) & 2047]
                        + sinLut1[x + a + 2048]
                        + sinLut1[y + a + 2048]
                        + sinLut2[x + b + 2048]);
                tx = tx & 255;
                ty = ty & 255;
                pixels[offset++] = texPixels[ ty * 256 + tx];
            }
        }
    }

    public BufferedImage getImage() {
        return image;
    }
}
